package stream;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


public class StreamService {

  public static final float UNIT = 1024;

  public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
    String s = null;
    try {
      s = FileUtils.readFileToString(new File("src/main/resources/index"), Charset.forName("utf-8"));
    } catch (IOException e) {
      e.printStackTrace();
    }

    Gson gson = new GsonBuilder().create();
    List<ReportBO> reportBOs = gson.fromJson(s, new TypeToken<ArrayList<ReportBO>>() {
    }.getType());

    System.out.println(reportBOs);

    Stream<Report> reportStream = reportBOs.stream().map(new Function<ReportBO, Report>() {
      @Override
      public Report apply(ReportBO reportBO) {
        AppIDBO appIDBO = convertResponse(reportBO.getIndex());
        if (appIDBO == null) return null;
        Report report = new Report();
        report.setAppid(appIDBO.getAppid());
        report.setTenantId(appIDBO.getTenantId());
        report.setIndex(appIDBO.getIndex());
        report.setLogtype(appIDBO.getLogType());
        report.setDocsCount(Long.valueOf(reportBO.getDocsCount()));
        String storeSize = reportBO.getStoreSize();
        String unmberStr = storeSize.substring(0, storeSize.length() - 2);
        String unit = storeSize.substring(storeSize.length() - 2);
        //单位 mb
        float unmber = 0;
        try {
          switch (unit) {
            case "kb":
              unmber = Float.valueOf(unmberStr) / UNIT;
              break;
            case "mb":
              unmber = Float.valueOf(unmberStr);
              break;
            case "gb":
              unmber = Float.valueOf(unmberStr) * UNIT;
              break;
            default:
              unmber = 999f;
              break;
          }
        } catch (NumberFormatException e) {
          e.printStackTrace();
        }
        report.setStoreSize(unmber);
        return report;
      }
    }).filter(new Predicate<Report>() {
      @Override
      public boolean test(Report report) {
        return report != null && report.getAppid() != null && report.getTenantId() != null;
      }
    });

    Map<String, List<Report>> reportsMap = reportStream.collect(Collectors.groupingBy(new Function<Report, String>() {
      @Override
      public String apply(Report report) {
        return report.getTenantId() + "_" + report.getAppid();
      }
    }));

    List<Report> reportLinkedList = new LinkedList<>();

    for (Map.Entry<String, List<Report>> stringListEntry : reportsMap.entrySet()) {
      List<Report> reports = stringListEntry.getValue();

      Long docsCount = reports.stream().collect(Collectors.summingLong(new ToLongFunction<Report>() {
        @Override
        public long applyAsLong(Report value) {
          return value.getDocsCount();
        }
      }));

      Double storeSize = reports.stream().collect(Collectors.summingDouble(new ToDoubleFunction<Report>() {
        @Override
        public double applyAsDouble(Report value) {
          return value.getStoreSize();
        }
      }));

      Report reportf = reports.get(0);
      Report reportc = new Report();
      BeanUtils.copyProperties(reportf, reportc);

      reportc.setIndexCount(reports.size());
      reportc.setDocsCount(docsCount);
      reportc.setStoreSize(storeSize.floatValue());

      reportLinkedList.add(reportc);
    }

    System.out.println(reportLinkedList);
    List<Report> collect = reportLinkedList.stream().sorted(new Comparator<Report>() {
      @Override
      public int compare(Report o1, Report o2) {
        return Long.compare(o2.getDocsCount(), o1.getDocsCount());
      }
    }).collect(Collectors.toList());


    Map<String, IntSummaryStatistics> collect1 = (Map<String, IntSummaryStatistics>) reportStream.collect(
            Collectors.groupingBy(new Function<Report, String>() {
                                    @Override
                                    public String apply(Report o) {
                                      return o.getAppid();
                                    }
                                  }, Collectors.summarizingInt(new ToIntFunction() {
                                                                 @Override
                                                                 public int applyAsInt(Object value) {
                                                                   Report report = (Report) value;
                                                                   return report.getDocsCount().intValue();
                                                                 }
                                                               }

                    )

            )
    );


    Map<String, IntSummaryStatistics> collect2 = (Map<String, IntSummaryStatistics>) reportStream.collect(
            Collectors.groupingBy(new Function<Report, String>() {
                                    @Override
                                    public String apply(Report o) {
                                      return o.getAppid();
                                    }
                                  }, Collectors.summarizingInt(new ToIntFunction() {
                      @Override
                      public int applyAsInt(Object value) {
                        Report report = (Report) value;
                        return report.getDocsCount().intValue();
                      }
                    })

            )
    );

    Map<String, Double> collect3 = reportStream.collect(
            Collectors.groupingBy(
                    new Function<Report, String>() {
                      @Override
                      public String apply(Report o) {
                        return o.getAppid();
                      }
                    },
                    Collectors.summingDouble(new ToDoubleFunction<Report>() {
                      @Override
                      public double applyAsDouble(Report value) {
                        return value.getStoreSize();
                      }
                    })
            )
    );

    List<Report> collect4 = reportLinkedList.stream().sorted(new Comparator<Report>() {
      @Override
      public int compare(Report o1, Report o2) {
        return Long.compare(o2.getDocsCount(), o1.getDocsCount());
      }
    }).collect(Collectors.toList());

    System.out.println(collect4);

  }


  /**
   * @param index eg: applog_dev_elk-log-demo_1369923265280311297_2021.07.27
   */
  public static AppIDBO convertResponse(String index) {
    AppIDBO appIDBo = new AppIDBO();
    String[] indexEle = index.split("_");
    if (indexEle.length < 4) return null;
    appIDBo.setLogType(indexEle[0]);
    appIDBo.setEnv(indexEle[1]);
    appIDBo.setAppid(indexEle[2]);
    appIDBo.setTenantId(indexEle[3]);
    appIDBo.setIndex(index.substring(0, index.lastIndexOf("_")) + "_*");

    String prefixEnvKey = indexEle[0] + '_' + indexEle[1];
    Map<String, String> topicMap = new HashMap<>();
    topicMap.put("shuneng_dev", "fnw_logging_kafka_topic");
    topicMap.put("shuneng_pro", "fnw_logging_kafka_topic_prod");
    topicMap.put("newshuneng_dev", "fnw_logging_kafka_topic_dev_new");
    topicMap.put("newshuneng_fat", "fnw_logging_kafka_topic_fat_new");
    topicMap.put("newshuneng_uat", "fnw_logging_kafka_topic_uat_new");
    topicMap.put("newshuneng_pro", "fnw_logging_kafka_topic_prod_new");
    appIDBo.setSrcTopic(topicMap.get(prefixEnvKey));
    return appIDBo;
  }

  public static final String s = "[[\n" +
          "  {\n" +
          "    \"health\" : \"green\",\n" +
          "    \"status\" : \"open\",\n" +
          "    \"index\" : \"shuneng_pro_cim-build-model_1387330602944675842_2022.04.27\",\n" +
          "    \"uuid\" : \"q2jT9az1TkWEf76sQpNvOQ\",\n" +
          "    \"pri\" : \"1\",\n" +
          "    \"rep\" : \"0\",\n" +
          "    \"docs.count\" : \"16472586\",\n" +
          "    \"docs.deleted\" : \"0\",\n" +
          "    \"store.size\" : \"26gb\",\n" +
          "    \"pri.store.size\" : \"26gb\"\n" +
          "  },\n" +
          "  {\n" +
          "    \"health\" : \"green\",\n" +
          "    \"status\" : \"open\",\n" +
          "    \"index\" : \"shuneng_pro_cim-build-model_1387330602944675842_2022.04.28\",\n" +
          "    \"uuid\" : \"LlSgPn5DQtaD65WABg3QNQ\",\n" +
          "    \"pri\" : \"1\",\n" +
          "    \"rep\" : \"0\",\n" +
          "    \"docs.count\" : \"16934861\",\n" +
          "    \"docs.deleted\" : \"0\",\n" +
          "    \"store.size\" : \"26.1gb\",\n" +
          "    \"pri.store.size\" : \"26.1gb\"\n" +
          "  },\n" +
          "  {\n" +
          "    \"health\" : \"green\",\n" +
          "    \"status\" : \"open\",\n" +
          "    \"index\" : \"shuneng_pro_cim-build-model_1387330602944675842_2022.04.29\",\n" +
          "    \"uuid\" : \"r16GKucGT4Gkaki-5S4F7A\",\n" +
          "    \"pri\" : \"1\",\n" +
          "    \"rep\" : \"0\",\n" +
          "    \"docs.count\" : \"16383387\",\n" +
          "    \"docs.deleted\" : \"0\",\n" +
          "    \"store.size\" : \"26.4gb\",\n" +
          "    \"pri.store.size\" : \"26.4gb\"\n" +
          "  },\n" +
          "  {\n" +
          "    \"health\" : \"green\",\n" +
          "    \"status\" : \"open\",\n" +
          "    \"index\" : \"shuneng_pro_fst-boiler-devops-app_1387330602944675842_2022.04.30\",\n" +
          "    \"uuid\" : \"1rcv0robQTWWXYtaI2GzMQ\",\n" +
          "    \"pri\" : \"1\",\n" +
          "    \"rep\" : \"0\",\n" +
          "    \"docs.count\" : \"571\",\n" +
          "    \"docs.deleted\" : \"0\",\n" +
          "    \"store.size\" : \"108.4kb\",\n" +
          "    \"pri.store.size\" : \"108.4kb\"\n" +
          "  },\n" +
          "  {\n" +
          "    \"health\" : \"green\",\n" +
          "    \"status\" : \"open\",\n" +
          "    \"index\" : \"shuneng_pro_carbon-credit-trading_1387330602944675842_2022.04.27\",\n" +
          "    \"uuid\" : \"dcQQE8PwTnSiW7itoj0f2A\",\n" +
          "    \"pri\" : \"1\",\n" +
          "    \"rep\" : \"0\",\n" +
          "    \"docs.count\" : \"18985\",\n" +
          "    \"docs.deleted\" : \"0\",\n" +
          "    \"store.size\" : \"2mb\",\n" +
          "    \"pri.store.size\" : \"2mb\"\n" +
          "  }]";
}

